package checkers3d.logic;

import checkers3d.presentation.GUIButton;
import checkers3d.presentation.GUIContainer;
import checkers3d.presentation.GUIPictureBox;
import checkers3d.presentation.IDrawable;
import checkers3d.presentation.IInputObserver;
import checkers3d.presentation.ParticleSystem;
import checkers3d.presentation.RenderResourceBitmap;
import checkers3d.presentation.UtilGUI;
import checkers3d.presentation.Vector;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.LinkedList;

/**
 * Displays the main menu. Shows the 3DCheckers logo and allows the user to
 * either start a new duel or exit to desktop. A new duel is started by adding
 * pushing a new Game on the GUIContainer stack in GameMaster. Exiting is done
 * by requesting a quit from GameMaster.
 *
 * @author Ruben Acuna
 */
public class MenuMain extends GUIContainer
{
    /**
     * The height in pixels of the particle emitter region.
     */
    private static final int PS_EMITTER_HEIGHT = 48;

    /**
     * The width in pixels of the particle emitter region.
     */
    private static final int PS_EMITTER_WIDTH = 128;

    /**
     * Particle system ffor the falling home pieces on the left.
     */
    private ParticleSystem psHomeCheckers;

    /**
     * Particle system for the falling visitor pieces on the right.
     */
    private ParticleSystem psVisitorCheckers;

    /**
     * Class constructor that creates a viewable GUIContainer. Displays a logo
     * and two buttons, for starting a duel or existing the program.
     */
    public MenuMain(Point windowSize)
    {
        //call parent constructor with screen screen;
        super(windowSize);

        LinkedList<IDrawable> buttons = new LinkedList<IDrawable>();

        //add the background
        addBackground(new GUIPictureBox("background.png", new Point (0, 0)), new Vector(20, 0));
        addBackground(new GUIPictureBox("background2.png", new Point (0, 0)), new Vector(-20, 0));
        addBackground(new GUIPictureBox("background3.png", new Point (0, 598)), new Vector(-20, 0));

        //add logo - not a button but we still want it aligned.
        buttons.add(new GUIPictureBox("button-logo.png", null));

        //add the duel button with behavior.
        buttons.add(new GUIButton("button-duel.png", null, new ObserverDuel()));

        //add the duel button with behavior.
        buttons.add(new GUIButton("button-newusers.png", null, new ObserverNewPlayer()));

        //add the start button with scenarios.
        buttons.add(new GUIButton("button-scenarios.png", null, new ObserverScenarios()));

        //add the start button with behavior.
        buttons.add(new GUIButton("button-load.png", null, new ObserverLoad()));

        //add the stats button with behavior
        buttons.add(new GUIButton(".\\images\\button-statistics.png", null, new ObserverStats()));

        //add the exit button with behavior.
        buttons.add(new GUIButton("button-exit.png", null, new ObserverExit()));

        //add the buttons to the GUIContainer.
        for(IDrawable component : buttons)
            add(component);

        //compute the positions of all components in the list.
        UtilGUI.computeLayoutCentered(getSize(), getSize().x / 2, buttons);

        //add particle systems.
        psHomeCheckers = new ParticleSystem(new Rectangle(0, -PS_EMITTER_HEIGHT * 2, PS_EMITTER_WIDTH, PS_EMITTER_HEIGHT),
                                            new Vector(1f, .8f),//velocity direction
                                            25f,                //velocity magnitude
                                            new Vector(0, 25f), //gravitational acceleration
                                            0f,                 //angular momentum
                                            0f,                 //draw scane change
                                            0,                  //life span of particles
                                            128,                //number of particles
                                            50,                 //delay between particle spawn
                                            true,
                                            this,
                                            new RenderResourceBitmap("player1tokenchecker.png"));

        psVisitorCheckers = new ParticleSystem(new Rectangle(getSize().x - PS_EMITTER_WIDTH, -PS_EMITTER_HEIGHT * 2, PS_EMITTER_WIDTH, PS_EMITTER_HEIGHT),
                                               new Vector(-1f, .8f),//velocity direction
                                               25f,                 //velocity magnitude
                                               new Vector(0, 25f),  //gravitational acceleration
                                               0f,                  //angular momentum
                                               0f,                  //draw scane change
                                               0,                   //life span of particles
                                               128,                 //number of particles
                                               50,                  //delay between particle spawn
                                               true,
                                               this,
                                               new RenderResourceBitmap("player2tokenchecker.png"));
    }
    
    /**
     * Informs the particle systems that a given amount of time in milliseconds
     * has elapsed. Used for animation.
     *
     * @param ms Milliseconds elapsed.
     */
    @Override
    public void tick(int ms)
    {
        super.tick(ms);

        psHomeCheckers.tick(ms);
        psVisitorCheckers.tick(ms);
    }

    /**
     * Returns a string representation of this object containing it's class name.
     *
     * @return String representation.
     */
    @Override
    public String toString()
    {
        return getClass().getName();
    }

    /**
     * IInputObserver for the duel button that creates the game setup window.
     */
    private class ObserverDuel implements IInputObserver
    {
        /**
         * Creates a menu for setting up a duel and pushes it on the render
         * stack.
         *
         * @param position Location of click within button.
         */
        public void onClick(Point position)
        {
            //push a window for creating a game onto the render stack.
            GameMaster.getInstance().addGUIContainer(new MenuNewGameLoginMP(getSize()));
        }

        /**
         * Key press observer that does nothing.
         *
         * @param key Key that was pressed.
         */
        public void onKeyPress(char key)
        {
            //do nothing.
        }
    }

    /**
     * IInputObserver for the new player login button that displays the player
     * creation window.
     */
    private class ObserverStats implements IInputObserver
    {
        /**
         * Creates a menu for viewing stats and pushes it on the render
         * stack.
         *
         * @param position Location of click within button.
         */
        public void onClick(Point position)
        {
            //push a window for viewing stats onto the render stack.
            GameMaster.getInstance().addGUIContainer(new MenuViewStats(getSize()));
        }

        /**
         * Key press observer that does nothing.
         *
         * @param key Key that was pressed.
         */
        public void onKeyPress(char key)
        {
            //do nothing.
        }
    }

    /**
     * IInputObserver for the stats button that displays the stats window.
     */
    private class ObserverNewPlayer implements IInputObserver
    {
        /**
         * Creates a menu for viewing stats and pushes it on the render
         * stack.
         *
         * @param position Location of click within button.
         */
        public void onClick(Point position)
        {
            //push a window for viewing stats onto the render stack.
            GameMaster.getInstance().addGUIContainer(new MenuNewPlayerLogin(getSize()));
        }

        /**
         * Key press observer that does nothing.
         *
         * @param key Key that was pressed.
         */
        public void onKeyPress(char key)
        {
            //do nothing.
        }
    }

    /**
     * IInputObserver for the scenario button that creates a scenario window.
     */
    private class ObserverScenarios implements IInputObserver
    {
        /**
         * Creates a menu for playing a scenario and pushes it on the render
         * stack.
         *
         * @param position Location of click within button.
         */
        public void onClick(Point position)
        {
            //push a window for creating a game onto the render stack.
            GameMaster.getInstance().addGUIContainer(new MenuScenarioSelect(getSize()));
        }

        /**
         * Key press observer that does nothing.
         *
         * @param key Key that was pressed.
         */
        public void onKeyPress(char key)
        {
            //do nothing.
        }
    }

    /**
     * IInputObserver for the load button that creates a loading window.
     */
    private class ObserverLoad implements IInputObserver
    {
        /**
         * Creates a menu for playing a loading a game and pushes it on the
         * render stack.
         *
         * @param position Location of click within button.
         */
        public void onClick(Point position)
        {
            //push a window for creating a game onto the render stack.
            GameMaster.getInstance().addGUIContainer(new MenuLoad(getSize()));
        }

        /**
         * Key press observer that does nothing.
         *
         * @param key Key that was pressed.
         */
        public void onKeyPress(char key)
        {
            //do nothing.
        }
    }

    /**
     * IInputObserver for the exit button that exits the program.
     */
    private class ObserverExit implements IInputObserver
    {
        /**
         * Exits the program by requesting end program state from GameMaster.
         *
         * @param position Location of click within button.
         */
        public void onClick(Point position)
        {
            //Request a program close state in GameMaster.
            GameMaster.getInstance().setAlive(false);
        }

        /**
         * Key press observer that does nothing.
         *
         * @param key Key that was pressed.
         */
        public void onKeyPress(char key)
        {
            //do nothing.
        }
    }
}